Latest update: December 2013
In this tutorial, we'll show you how to upload a file to your FlashAir with
upload.cgi.
This tutorial builds off of
Android Tutorial 4: Displaying Image
Thumbnails.
We're going to sort images on your FlashAir by title, and by date.
Warning: If this operation is used incorrectly, the FlashAir file system may become corrupted and you may lose your data. Host devices, like a PC, can cache the contents of the SD card (FAT), but will not see changes made by upload.cgi. Therefore, a FAT file system conflict may occur if changes are made by the host device and upload.cgi at the same time. After using upload.cgi, re-insert the SD card and the host device will be able to see your changes.
Here's the screen layour of our app:
We will add screen3:"Date list", and screen4:"Operation Screen" to iOS Tutorial 4: Displaying Image Thumbnails.
We'll be adding a Date List button to Screen 1 (Content list). A list, sorted by date, will be displayed when it's tapped.
When the user taps on an item, Screen 4 (the Operation Screen) will be displayed.
First lets add the "Date List" button to
iOS Tutorial 4: Displaying Image Thumbnails.
Next, add a sort condition so we only see image
files.
See the sample code for more details!
This file will be identical to the copy in
iOS Tutorial 3: Downloading Content.
Please refer to that tutorial for an explanation of the implementation.
The "Date List" will display images in the selected folder (from the Content List), as well as a saved date and title. Notes and title information will be saved in the same folder as the image, stored in a timestamped file (YYYYMMDD.txt). The title will be saved as the top line, and notes will be on the second. This file will be saved by screen 5 (the "Opertaion Screen"). See below for details.
First, lets get the date information for the images.
NSMutableDictionary *ret = nil;
// Find unique dates of files
NSMutableSet *dates = [NSMutableSet set];
for (NSString *fileInfo in self.files) {
NSArray *tokens = [fileInfo componentsSeparatedByString:@","];
// Skip if it is the signature line or an empty line or not image file.
NSString *dir = [tokens objectAtIndex:0];
NSString *filename = [tokens objectAtIndex:1];
NSString *ext = [[filename pathExtension] lowercaseString];
if([dir isEqualToString:@""] || [dir isEqualToString:@"WLANSD_FILELIST\r"] ||
!([ext isEqualToString:@"jpg"] || [ext isEqualToString:@"jpeg"] ||
[ext isEqualToString:@"png"] || [ext isEqualToString:@"jpe"])){
continue;
}
// Add date.
[dates addObject:[tokens objectAtIndex:4]];
}
Next, the title!
// Load existing memo.
ret = [NSMutableDictionary dictionary];
NSDateFormatter *toFormatter = [[NSDateFormatter alloc] init];
[toFormatter setDateFormat:@"yyyyMMdd"]; //for filename
NSDateFormatter *tostrFormatter = [[NSDateFormatter alloc] init];
[tostrFormatter setDateFormat:@"yyyy/MM/dd"]; //for show display
for (NSString *date in dates) {
NSError *error = nil;
// Convert date number to string.
NSString *sDate= [toFormatter stringFromDate:[self dateAsDate:date]];
NSString *strDate= [tostrFormatter stringFromDate:[self dateAsDate:date]];
// Make up URL to the memo file.
NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:@"http://flashair%@/%@.txt",
self.path, sDate]];
// Get memo contents from the FlashAir.
NSString *title = @"";
NSString *body = @"";
NSString *memoData =[NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding
error:&error];
if ( ![error.domain isEqualToString:NSCocoaErrorDomain] && [memoData rangeOfString:@"DOCTYPE"
options:NSCaseInsensitiveSearch].location == NSNotFound) {
// Success to get existing memo.
NSArray *data = [memoData componentsSeparatedByString:@"\n"];
title = [data objectAtIndex:0];
body = [data objectAtIndex:1];
}
// Add this memo to the list.
NSDictionary *memo = [NSDictionary dictionaryWithObjectsAndKeys:
title, @"title",
body, @"body",
strDate, @"date",
nil];
[ret setObject:memo forKey:sDate];
}
This screen will edit and save the YYYYMMDD.txt file (which holds the title and notes of each date).
In order to save our file to the FlashAir, we need to use upload.cgi.
UPLOAD=1
in the
CONFIG file
WRITEPROTECT
commandUPDIR
commandFTIME
commandSteps 1-3 need to be done manually, and then we'll continue with steps 4-6.
// Set Write-Protect and upload directory and System-Time
// Make System-Time
NSDate *systemdate = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateCompnents;
dateCompnents =[calendar components:NSYearCalendarUnit
| NSMonthCalendarUnit
| NSDayCalendarUnit
| NSHourCalendarUnit
| NSMinuteCalendarUnit
| NSSecondCalendarUnit fromDate:systemdate];
NSInteger year =([dateCompnents year]-1980) << 9;
NSInteger month = ([dateCompnents month]) << 5;
NSInteger day = [dateCompnents day];
NSInteger hour = [dateCompnents hour] << 11;
NSInteger minute = [dateCompnents minute]<< 5;
NSInteger second = floor([dateCompnents second]/2);
NSString *datePart = [@"0x" stringByAppendingString:[NSString stringWithFormat:@"%x%x" ,
year+month+day,hour+minute+second]];
// Make Filename
NSString *filename=[[self.date stringByReplacingOccurrencesOfString:@"/" withString:@""]
stringByAppendingString :@".txt"];
// Make url
NSString *urlStr = @"http://flashair/upload.cgi";
urlStr = [urlStr stringByAppendingString:@"?WRITEPROTECT=ON&UPDIR="];
urlStr = [urlStr stringByAppendingString:self.path];
urlStr = [urlStr stringByAppendingString:@"&FTIME="];
urlStr = [urlStr stringByAppendingString:datePart];
NSURL *url = [NSURL URLWithString:urlStr];
// Run cgi
NSError *error;
NSString *rtnStr =[NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
if ([error.domain isEqualToString:NSCocoaErrorDomain]){
NSLog(@"upload.cgi %@\n",error);
return;
}else{
if(![rtnStr isEqualToString:@"SUCCESS"]){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:self.title
message:@"upload.cgi:setup failed" delegate:nil
cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
[alert show];
return;
}
}
Next, step 7!.
// File upload
// Make Data
self.memoTitle = self.textFieldTitle.text;
self.memoBody = self.textViewMemo.text;
NSString *memoData = [[self.memoTitle stringByAppendingString:@"\n"]
stringByAppendingString:self.memoBody];
NSData *textData=[memoData dataUsingEncoding:NSUTF8StringEncoding ];
//url
url=[NSURL URLWithString:@"http://flashair/upload.cgi"];
//boundary
CFUUIDRef uuid = CFUUIDCreate(nil);
CFStringRef uuidString = CFUUIDCreateString(nil, uuid);
CFRelease(uuid);
NSString *boundary = [NSString stringWithFormat:@"flashair-%@",uuidString];
//header
NSString *header = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
//body
NSMutableData *body=[NSMutableData data];
[body appendData:[[NSString stringWithFormat:@"--%@\r\n",boundary]
dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\";
filename=\"%@\"\r\n",filename] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Type: text/plain\r\n\r\n"]
dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:textData];
[body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary]
dataUsingEncoding:NSUTF8StringEncoding]];
//Request
NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request addValue:header forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:body];
NSURLResponse *response;
NSData *result = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
rtnStr=[[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
if ([error.domain isEqualToString:NSCocoaErrorDomain]){
NSLog(@"upload.cgi %@\n",error);
return;
}else{
if([rtnStr rangeOfString:@"Success"].location==NSNotFound){ //v2.0
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:self.title
message:@"upload.cgi: POST failed" delegate:nil
cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
[alert show];
return;
}
}
Let's set a title and save some notes!
Tap the Date List button.
Tap 2013/03/03.
The operation screen for 2013/03/03 is displayed.
Enter a title and some notes, then tap the Done button.
When you return to the previous screen, you'll see your changes have been saved!
ios_tutorial_07.zip (62KB)
All sample code on this page is licensed under BSD 2-Clause License